/**
 * OSAmI: Open Source Ambient Intelligence
 * A simple publish/subscribe/dispatch API (based on multicast communications) for constrained devices.
 * Copyright (C) Lionel Debroux 2006 (as a TER/Magistere M1 student in the LSR-IMAG-ADELE team, for a demo in the H-Omega project)
 * Copyright (C) Lionel Debroux 2010 (as an engineer in the LCIS-INPG-CTSYS team, for a pre-demo in the FR part of the OSAMI project)
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA
 */

package fr.imag.adele.homega.impl.unicast;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class (surprisingly ?) provides a testcase for the multicast API.
 */
public class UnicastAPITest {

	private static final String MULTICAST_ADDRESS01 = "FF02:0:0:0:0:0:0:99"; //"226.0.0.1";
	private static final String MULTICAST_ADDRESS02 = "FF02:0:0:0:0:0:0:9A"; //"226.0.0.2";
	private static final String MULTICAST_ADDRESS03 = "FF02:0:0:0:0:0:0:9B"; //"226.0.0.3";
	private static final String MULTICAST_ADDRESS11 = "FF02:0:0:0:0:0:0:9C"; //"226.1.0.1";
	private static final String MULTICAST_ADDRESS12 = "FF02:0:0:0:0:0:0:9D"; //"226.1.0.2";

	private static final int NAP_TIME = 20;

	/**
	 * Test program for Unicast API
	 */
	public static void main(String[] args) {

		// A single message handler.
		UnicastHandler handler = null;
		// Publishers.
		UnicastSender sender1 = null;
		UnicastSender sender2 = null;
		UnicastSender sender3 = null;
		UnicastSender sender4 = null;
		// Subscribers.
		UnicastReceiver receiver1 = null;
		UnicastReceiver receiver2 = null;
		UnicastReceiver receiver3 = null;
		UnicastReceiver receiver4 = null;
		UnicastReceiver receiver5 = null;
		UnicastReceiver receiver6 = null;

		try {
			Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).setLevel(Level.ALL);
			System.runFinalizersOnExit(true); // XXX

			// Create handler first.
			handler = new UnicastHandlerImpl();

			// Create subscribers before publishers.
			System.out.println("=== Creating subscribers ===");
			receiver1 = new UnicastReceiverImpl("r11_1");
			receiver2 = new UnicastReceiverImpl("r11_2");
			receiver3 = new UnicastReceiverImpl("r21");
			receiver4 = new UnicastReceiverImpl("r31");
			receiver5 = new UnicastReceiverImpl("r12");
			receiver6 = new UnicastReceiverImpl("monitor");

			System.out.println("=== Creating publishers ===");
			sender1 = new UnicastSenderImpl("s11");
			sender2 = new UnicastSenderImpl("s12");
			sender3 = new UnicastSenderImpl("s13");
			sender4 = new UnicastSenderImpl("s21");
		Thread.sleep(NAP_TIME);

			System.out.println("=== Registrations before any register operations ===");
			handler.printMembers();
			receiver1.register(handler, MULTICAST_ADDRESS01, 10001); // r11_1
			receiver2.register(handler, MULTICAST_ADDRESS01, 10001); // r11_2
			receiver3.register(handler, MULTICAST_ADDRESS02, 10002); // r21
			receiver4.register(handler, MULTICAST_ADDRESS03, 10003); // r31
			receiver5.register(handler, MULTICAST_ADDRESS01, 10004); // r12
/*
			receiver1.register(handler, MULTICAST_ADDRESS01, 10001);
			receiver2.register(handler, MULTICAST_ADDRESS01, 10001);
			receiver3.register(handler, MULTICAST_ADDRESS02, 10001);
			receiver4.register(handler, MULTICAST_ADDRESS03, 10001);
			receiver5.register(handler, MULTICAST_ADDRESS01, 10002);
			handler.printMembers();
*/
		Thread.sleep(NAP_TIME);

			System.out.println("=== Registrations after the first batch of register operations ===");
			handler.printMembers();
		Thread.sleep(NAP_TIME);

			// "Monitor": registers to all topics.
			receiver6.register(handler, MULTICAST_ADDRESS01, 10001); // monitor
			receiver6.register(handler, MULTICAST_ADDRESS02, 10002); // monitor
			receiver6.register(handler, MULTICAST_ADDRESS03, 10003); // monitor
			receiver6.register(handler, MULTICAST_ADDRESS01, 10004); // monitor
/*
			receiver6.register(handler, MULTICAST_ADDRESS01, 10001);
			receiver6.register(handler, MULTICAST_ADDRESS01, 10002);
			receiver6.register(handler, MULTICAST_ADDRESS02, 10001);
			receiver6.register(handler, MULTICAST_ADDRESS03, 10001);
*/
		Thread.sleep(NAP_TIME);

			// Print registrations.
			System.out.println("=== Registrations after the registering the monitor ===");
			handler.printMembers();
		Thread.sleep(NAP_TIME);

			System.out.println("=== Binding senders ===");
			// Senders bound on the same address.
			sender1.bind(MULTICAST_ADDRESS11, 20001); // s11
			sender2.bind(MULTICAST_ADDRESS11, 20002); // s12
			sender3.bind(MULTICAST_ADDRESS11, 20003); // s13
			sender4.bind(MULTICAST_ADDRESS12, 20004); // s21
		Thread.sleep(NAP_TIME);

			// Send to multiple subscribers.
			System.out.println("=== Sending hellos ===");
			sender1.send(MULTICAST_ADDRESS01, 10001, "Hello from sender1 !");
			sender2.send(MULTICAST_ADDRESS02, 10002, "Hello from sender2 !");
			sender3.send(MULTICAST_ADDRESS03, 10003, "Hello from sender3 !");
			sender4.send(MULTICAST_ADDRESS01, 10004, "Hello from sender4 !");
/*
			sender1.send(MULTICAST_ADDRESS01, 10001, "Hello from sender1 !");
			sender2.send(MULTICAST_ADDRESS02, 10001, "Hello from sender2 !");
			sender3.send(MULTICAST_ADDRESS03, 10001, "Hello from sender3 !");
			sender4.send(MULTICAST_ADDRESS01, 10002, "Hello from sender4 !");
*/
		Thread.sleep(NAP_TIME);

			System.out.println("Over !");

		} catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			if (receiver6 != null) receiver6.shutdown();
			if (receiver5 != null) receiver5.shutdown();
			if (receiver4 != null) receiver4.shutdown();
			if (receiver3 != null) receiver3.shutdown();
			if (receiver2 != null) receiver2.shutdown();
			if (receiver1 != null) receiver1.shutdown();

			if (sender4 != null)   sender4.shutdown();
			if (sender3 != null)   sender3.shutdown();
			if (sender2 != null)   sender2.shutdown();
			if (sender1 != null)   sender1.shutdown();

			if (handler != null)   handler.shutdown();
		}
	}

}
